<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2015/8/3
 * Time: 9:28
 */

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use p5\objects\ArrayUtils;
use p5\objects\CollectionUtils;

class BaseCommand extends Command
{
    private $database = "";
    private $tables = "*";

    public function putCommonVariables(&$data)
    {
        $data["dollar"] = '$';
    }

    public function loadTables()
    {
        if (is_array($this->tables)) {
            return $this->tables;
        }
        if ($this->tables != "*") {
            return [$this->tables];
        }
        $database = $this->getDatabase();
        $sql = "select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='$database' and TABLE_TYPE='BASE TABLE'";
        $list = DB::select($sql);
        return CollectionUtils::pick($list, "TABLE_NAME");
    }

    public function getMetaData($table = "")
    {
        $database = $this->getDatabase();
        try {
            $limits = empty($table) ? "" : " and TABLE_NAME='$table' ";
            $sql = "SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = '$database' $limits ORDER BY TABLE_NAME";
            $columns = \DB::select($sql);
            Log::debug($sql);

            $sql = "SELECT * FROM information_schema.`KEY_COLUMN_USAGE` WHERE CONSTRAINT_SCHEMA = '$database' AND CONSTRAINT_NAME = 'PRIMARY' $limits ORDER BY TABLE_NAME";
            $keys = \DB::select($sql);
            $result = self::prepareMetadata($columns, $keys);
            return $result;
        } catch (\Exception $e) {
            var_dump($e->getTrace());
            return [];
        }
    }


    static public function prepareMetadata($columns, $keys)
    {
        $meta = [];
        foreach ($columns as $column) {
            $table = $column->TABLE_NAME;

            if (self::isIgnoreColumn($column)) {
                continue;
            }

            $primary = self::findPrimary($table, $keys);
            $meta['primary'] = $primary;
            $meta[$table]['primary'] = $primary;
            $meta['primary_key'] = $primary;
            $meta[$table]['primary_key'] = $primary;
            $meta[$table]['columns'][] = [
                'name' => $column->COLUMN_NAME,
                'type' => self::toPHPType($column->DATA_TYPE),
                'required' => ($column->IS_NULLABLE == "YES") ? 0 : 1,
                'rules' => self::getColumnValidateRules($column),
                'comment' => $column->COLUMN_COMMENT,
                'extra' => $column->EXTRA,
            ];
        }

        return $meta;
    }

    static public function toPHPType($type)
    {
        if ($type == "varchar" || $type == "char" || $type == "nvarchar") {
            return "string";
        }
        if ($type == "int" || $type == "tinyint" || $type == "smallint" || $type == "bigint") {
            return "int";
        }
        if ($type == "float" || $type == "decimal") {
            return $type;
        }
        return "";
    }

    static public function isIgnoreColumn($column)
    {
        return false;
    }

    static public function getColumnValidateRules($column)
    {
        $rules = array();
        if ($column->IS_NULLABLE == "NO") {
            array_push($rules, "required");
        }
        if ($column->DATA_TYPE == "int" || $column->DATA_TYPE == "tinyint" || $column->DATA_TYPE == "smallint") {
            array_push($rules, "integer");
        } else if ($column->DATA_TYPE == "varchar") {
            array_push($rules, "max:" . $column->CHARACTER_MAXIMUM_LENGTH);
        } else if ($column->DATA_TYPE == "date") {
            array_push($rules, "date");
        } else if ($column->DATA_TYPE == "datetime") {
            array_push($rules, "date");
        } else if ($column->DATA_TYPE == "timestamp") {
            array_push($rules, "date");
        } else if ($column->DATA_TYPE == "decimal") {
            array_push($rules, "numeric");
        }

        return implode("|", $rules);
    }

    static public function findPrimary($table, $keys)
    {
        if (empty($keys)) {
            return "";
        }
        foreach ($keys as $key) {
            if ($key->TABLE_NAME == $table && $key->CONSTRAINT_NAME == 'PRIMARY')
                return $key->COLUMN_NAME;
        }
        return $keys[0]->COLUMN_NAME;
    }

    public function to_camel($string)
    {
        $matrix = explode("_", $string);
        //var_dump($matrix);
        for ($i = 0; $i < count($matrix); $i++) {
            $matrix[$i] = Str::title($matrix[$i]);
        }
        //var_dump($matrix);
        return implode("", $matrix);
    }

    /**
     * @return string
     */
    public function getDatabase()
    {
        if (empty($this->database)) {
            return env('DB_DATABASE');
        }
        return $this->database;
    }

    /**
     * @param string $database
     */
    public function setDatabase($database)
    {
        $this->database = $database;
    }

    /**
     * @return string
     */
    public function getTables()
    {
        return $this->tables;
    }

    /**
     * @param string $tables
     */
    public function setTables($tables)
    {
        $this->tables = $tables;
    }


    protected function formatTargets($expression)
    {
        $expression = empty($expression) ? "*" : $expression;
        $defaultDb = env("DB_DATABASE");
        if ($expression == "*") {
            $this->setDatabase($defaultDb);
            $this->setTables("*");
            return;
        }
        $matrix = explode(".", $expression);
        $size = count($matrix);
        if ($size == 1) {
            $this->setDatabase($defaultDb);
            $this->setTables($expression);
            return;
        }
        if ($size == 2) {
            $this->setDatabase($matrix[0]);
            $this->setTables($matrix[1]);
            return;
        }
    }


}